home *** CD-ROM | disk | FTP | other *** search
- ;-*- Syntax: Zetalisp; Mode: Lisp; Package: BOXER; base: 10; fonts: CPTFONT; -*-
-
- ;;; (C) Copyright 1985 Massachusetts Institute of Technology
- ;;;
- ;;; Permission to use, copy, modify, distribute, and sell this software
- ;;; and its documentation for any purpose is hereby granted without fee,
- ;;; provided that the above copyright notice appear in all copies and that
- ;;; both that copyright notice and this permission notice appear in
- ;;; supporting documentation, and that the name of M.I.T. not be used in
- ;;; advertising or publicity pertaining to distribution of the software
- ;;; without specific, written prior permission. M.I.T. makes no
- ;;; representations about the suitability of this software for any
- ;;; purpose. It is provided "as is" without express or implied warranty.
- ;;;
-
- ;;;MOUSE(or other pointing thing) tracking stuff
-
- (DEFCONST %%KBD-MOUSE-UP-STATE #O1601
- "A byte specifier which determines if a mouse button is being held up or down. ")
-
- (DEFVAR *MOUSE-BP* (MAKE-BP :FIXED))
-
- (DEFVAR *FOLLOWING-MOUSE-REGION* NIL)
-
- (DEFVAR *MOUSE-BUTTONS-CURRENT-STATE* 0
- "Keeps track of which mouse buttons are being held down")
-
- (DEFVAR *MOUSE-CLICKS-ONLY* NIL
- "Determines whether the mouse handler will keep track of buttons which are held (not just
- clicked")
-
- (DEFVAR *BUTTON-BEING-HELD* NIL
- "The number of the button currently being held down. ")
-
- (DEFVAR *MOUSE-SIGNAL-HOLD-TIME* 400000.
- "The amount of time (in microseconds) a mouse button must be held down to signal that it is being held and not clicked. ")
-
- (DEFVAR *MOUSE-DISAPPEARING-TIMEOUT* 120.
- "The amount of time in 60ths of a second that a mouse will wait before disappearing.")
-
- (DEFVAR *MOUSE-BOX-X* 0.
- "The X position of the mouse in coordinates based on the upper left hand corner of the
- lowest Box which contains the Mouse.")
-
- (DEFVAR *MOUSE-BOX-Y* 0.
- "The Y position of the mouse in coordinates based on the upper left hand corner of the
- lowest Box which contains the Mouse.")
-
- (DEFSUBST VISIBLE-NAME-ROW? (SCREEN-BOX)
- (AND (TELL (TELL SCREEN-BOX :ACTUAL-OBJ) :NAME-ROW)
- (NEQ (OUTERMOST-SCREEN-BOX) SCREEN-BOX)))
-
- (DEFSUBST SCREEN-BOXES-IN-ROW (SCREEN-ROW)
- (SUBSET #'SCREEN-BOX? (TELL SCREEN-ROW :INFERIORS)))
-
- (DEFSUBST POSITION-IN-SCREEN-OBJ? (X Y SCREEN-OBJ)
- (AND (INCLUSIVE-BETWEEN? Y 0 (SCREEN-OBJ-HEI SCREEN-OBJ))
- (OR (SCREEN-ROW? SCREEN-OBJ)
- (INCLUSIVE-BETWEEN? X 0 (SCREEN-OBJ-WID SCREEN-OBJ)))))
-
- (DEFUN FIND-INF-SCREEN-BOX-IN-SUP-SCREEN-ROW (X Y SCREEN-BOXES)
- (LOOP FOR SCREEN-BOX IN SCREEN-BOXES
- FOR RELATIVE-X = (- X (SCREEN-OBJ-X-OFFSET SCREEN-BOX))
- FOR RELATIVE-Y = (- Y (SCREEN-OBJ-Y-OFFSET SCREEN-BOX))
- WHEN (POSITION-IN-SCREEN-OBJ? RELATIVE-X RELATIVE-Y SCREEN-BOX)
- RETURN SCREEN-BOX))
-
- (DEFUN GET-CHA-NO (X LIST-OF-CHAS)
- (LOOP FOR SCREEN-CHA IN LIST-OF-CHAS
- SUM (SCREEN-OBJECT-WIDTH SCREEN-CHA) INTO ACC-WID
- COUNT T INTO CHA-NO
- WHEN ( ACC-WID X)
- RETURN (1- CHA-NO)
- FINALLY (RETURN (LENGTH LIST-OF-CHAS))))
-
- (DEFMETHOD (SCREEN-ROW :FIND-BP-VALUES) (SUPERIOR-X SUPERIOR-Y)
- (LET* ((X (- SUPERIOR-X X-OFFSET))
- (Y (- SUPERIOR-Y Y-OFFSET))
- (WITHIN-BOX (FIND-INF-SCREEN-BOX-IN-SUP-SCREEN-ROW X Y (SCREEN-BOXES-IN-ROW SELF))))
- (IF (NULL WITHIN-BOX)
- (VALUES ACTUAL-OBJ (GET-CHA-NO X SCREEN-CHAS) SCREEN-BOX SUPERIOR-X SUPERIOR-Y)
- (TELL WITHIN-BOX :FIND-BP-VALUES X Y))))
-
- (DEFMETHOD (SCREEN-BOX :GET-AREA-OF-BOX) (X Y)
- "Returns the part of the box which (X, Y) is pointing to which can be a SCREEN-ROW,
- or one of the following keywords :NAME, :UNDERNAME, :LAST or NIL if (X, Y) is not inside
- a portion of the box. "
- (MULTIPLE-VALUE-BIND (IL IT IR IB)
- (SCREEN-BOX-BORDERS-FN ':BORDER-WIDS SELF)
- (COND ((AND (EQ (TELL SELF :DISPLAY-STYLE) ':SHRUNK)
- (INCLUSIVE-BETWEEN? X IL (- WID IR))
- (INCLUSIVE-BETWEEN? Y (// IT 2) (- HEI IB)))
- :INSIDE)
- ((AND (INCLUSIVE-BETWEEN? X IL (- WID IR))
- (INCLUSIVE-BETWEEN? Y IT (- HEI IB)))
- ;; Pointing to main area of box (where the screen rows are)
- (IF (#+SYMBOLICS LISTP #-SYMBOLICS CONSP SCREEN-ROWS)
- (FIND-INF-SCREEN-ROW-IN-SUP-SCREEN-BOX X Y SCREEN-ROWS)
- ':INSIDE))
- ((AND (INCLUSIVE-BETWEEN? X IL (- WID IR))
- (INCLUSIVE-BETWEEN? Y (// IT 2) IT))
- :TOP)
- ((VISIBLE-NAME-ROW? SELF)
- ;; must be pointing somewhere else
- (MULTIPLE-VALUE-BIND (TAB-FULL-WID TAB-FULL-HEI)
- (SCREEN-BOX-BORDERS-FN ':TAB-SPACE SELF)
- (MULTIPLE-VALUE-BIND (TAB-X TAB-Y)
- (SCREEN-BOX-BORDERS-FN ':TAB-OFFSETS SELF)
- (COND ((AND (< X TAB-FULL-WID) (> Y TAB-FULL-HEI)) :UNDERNAME)
- ((AND (INCLUSIVE-BETWEEN? X TAB-X TAB-FULL-WID)
- (INCLUSIVE-BETWEEN? Y TAB-Y TAB-FULL-HEI)) :NAME))))))))
-
- (DEFMETHOD (GRAPHICS-SCREEN-BOX :GET-AREA-OF-BOX) (X Y)
- (MULTIPLE-VALUE-BIND (IL IT IR IB)
- (SCREEN-BOX-BORDERS-FN ':BORDER-WIDS SELF)
- (COND ((AND (INCLUSIVE-BETWEEN? X IL (- WID IR))
- (INCLUSIVE-BETWEEN? Y (// IT 2) (- HEI IB)))
- ;; Pointing to main area of box (where the graphics sheet is)
- :INSIDE)
- ((AND (INCLUSIVE-BETWEEN? X IL (- WID IR))
- (INCLUSIVE-BETWEEN? Y (// IT 2) IT))
- :TOP)
- ((VISIBLE-NAME-ROW? SELF)
- ;; must be pointing somewhere else
- (MULTIPLE-VALUE-BIND (TAB-FULL-WID TAB-FULL-HEI)
- (SCREEN-BOX-BORDERS-FN ':TAB-SPACE SELF)
- (MULTIPLE-VALUE-BIND (TAB-X TAB-Y)
- (SCREEN-BOX-BORDERS-FN ':TAB-OFFSETS SELF)
- (COND ((AND (< X TAB-FULL-WID) (> Y TAB-FULL-HEI)) :UNDERNAME)
- ((AND (INCLUSIVE-BETWEEN? X TAB-X TAB-FULL-WID)
- (INCLUSIVE-BETWEEN? Y TAB-Y TAB-FULL-HEI)) :NAME))))))))
-
- (DEFUN FIND-INF-SCREEN-ROW-IN-SUP-SCREEN-BOX (X Y SCREEN-ROWS)
- (LOOP FOR SCREEN-ROW IN SCREEN-ROWS
- FOR RELATIVE-X = (- X (SCREEN-OBJ-X-OFFSET SCREEN-ROW))
- FOR RELATIVE-Y = (- Y (SCREEN-OBJ-Y-OFFSET SCREEN-ROW))
- WHEN (POSITION-IN-SCREEN-OBJ? RELATIVE-X RELATIVE-Y SCREEN-ROW)
- RETURN SCREEN-ROW
- FINALLY (RETURN :LAST)))
-
- (DEFMETHOD (SCREEN-BOX :FIND-BP-VALUES)
- (SUPERIOR-X SUPERIOR-Y &OPTIONAL (WINDOW *BOXER-PANE*))
- (LET* ((X (- SUPERIOR-X X-OFFSET))
- (Y (- SUPERIOR-Y Y-OFFSET))
- (WITHIN-AREA (TELL SELF :GET-AREA-OF-BOX X Y)))
- (COND ((AND (EQ SELF (OUTERMOST-SCREEN-BOX WINDOW)) (NULL WITHIN-AREA))
- (MULTIPLE-VALUE-BIND (ROW CHA-NO)
- (BOX-FIRST-BP-VALUES ACTUAL-OBJ)
- (VALUES ROW CHA-NO SELF X Y)))
- ((NULL WITHIN-AREA)
- (MULTIPLE-VALUE-BIND (ROW CHA-NO)
- (BOX-SELF-BP-VALUES ACTUAL-OBJ)
- (VALUES ROW CHA-NO SUPERIOR-SCREEN-BOX
- (+ (SCREEN-OBJ-X-OFFSET SCREEN-ROW) SUPERIOR-X)
- (+ (SCREEN-OBJ-Y-OFFSET SCREEN-ROW) SUPERIOR-Y))))
- ((SCREEN-ROW? WITHIN-AREA)
- (TELL WITHIN-AREA :FIND-BP-VALUES X Y))
- ((EQ WITHIN-AREA :LAST)
- (TELL (CAR (LAST SCREEN-ROWS)) :FIND-BP-VALUES X Y))
- ((EQ WITHIN-AREA :INSIDE)
- (MULTIPLE-VALUE-BIND (ROW CHA-NO)
- (BOX-FIRST-BP-VALUES ACTUAL-OBJ)
- (VALUES ROW CHA-NO SELF X Y)))
- ((EQ WITHIN-AREA :TOP)
- (MULTIPLE-VALUE-BIND (ROW CHA-NO)
- (BOX-FIRST-BP-VALUES ACTUAL-OBJ)
- (VALUES ROW CHA-NO SELF X Y)))
- ((EQ WITHIN-AREA :UNDERNAME)
- (MULTIPLE-VALUE-BIND (ROW CHA-NO)
- (BOX-SELF-BP-VALUES ACTUAL-OBJ)
- (VALUES ROW CHA-NO SUPERIOR-SCREEN-BOX
- (+ (SCREEN-OBJ-X-OFFSET SCREEN-ROW) SUPERIOR-X)
- (+ (SCREEN-OBJ-Y-OFFSET SCREEN-ROW) SUPERIOR-Y))))
- ((EQ WITHIN-AREA :NAME)
- (LET ((NAME-ROW (TELL ACTUAL-OBJ :NAME-ROW)))
- (VALUES NAME-ROW (GET-CHA-NO X (TELL NAME-ROW :CHAS)) SELF X Y)))
- (T (FERROR "Can't find a place in ~A for position ~D, ~D" SELF X Y)))))
-
- (DEFUN SCREEN-OBJ-AT-POSITION (X Y &OPTIONAL (WINDOW *BOXER-PANE*))
- "Throws back a ROW, CHA-NO, SCREEN-BOX and a position relative to the SCREEN-BOX based on
- the present location of the mouse. "
- (LET ((SUPERIOR-X (TV:SHEET-INSIDE-LEFT WINDOW))
- (SUPERIOR-Y (TV:SHEET-INSIDE-TOP WINDOW))
- (SCREEN-OBJ (OUTERMOST-SCREEN-BOX WINDOW)))
- (CHECK-SCREEN-OBJ-ARG SCREEN-OBJ)
- (WITH-FONT-MAP-BOUND (*BOXER-PANE*)
- (TELL SCREEN-OBJ :FIND-BP-VALUES (- X SUPERIOR-X) (- Y SUPERIOR-Y) WINDOW))))
-
- ;;; This shouldn't be consing up a BP every time ....
- (DEFMACRO WITH-MOUSE-BP-BOUND ((X Y WINDOW) &BODY BODY)
- "This macro sets up an environment where MOUSE-BP is bound to a BP which indicates
- where in the actual structure the mouse is pointing to. MOUSE-SCREEN-BOX is also
- bound to the screen box which the mouse is pointing to. "
- `(LET ((MOUSE-BP (MAKE-BP ':FIXED)))
- (MULTIPLE-VALUE-BIND (MOUSE-ROW MOUSE-CHA-NO MOUSE-SCREEN-BOX)
- (SCREEN-OBJ-AT-POSITION ,X ,Y ,WINDOW)
- (UNWIND-PROTECT
- (PROGN
- (SET-BP-ROW MOUSE-BP MOUSE-ROW)
- (SET-BP-CHA-NO MOUSE-BP MOUSE-CHA-NO)
- (SET-BP-SCREEN-BOX MOUSE-BP MOUSE-SCREEN-BOX)
- . ,BODY)
- (TELL-CHECK-NIL (BP-ROW MOUSE-BP) :DELETE-BP MOUSE-BP)))))
-
- (DEFMETHOD (BOXER-PANE :WHO-LINE-DOCUMENTATION-STRING) ()
- (IF (TELL-CHECK-NIL *SPRITE-BLINKER* :SELECTED-SPRITE)
- (LET ((WHO-LINE
- (TELL-CHECK-NIL
- (CDR (TELL-CHECK-NIL (SEND (SEND *SPRITE-BLINKER* :SELECTED-SPRITE)
- :SPRITE-BOX)
- :LOOKUP-STATIC-VARIABLE-IN-BOX-ONLY 'BU:WHO-LINE))
- :TEXT-STRING)))
- (OR WHO-LINE " ** Sprite-defined-clicks ** "))
- WHO-LINE-DOCUMENTATION-STRING))
-
- ;;;; BOXER Mouse handlers
-
- ;;; the (default) simple ones that we know will work
-
- (DEFUN DEFAULT-MOUSE-ENTERS-WINDOW-HANDLER (WINDOW)
- ;; For now, just make the mouse blinker be an ordinary arrow,
- ;; and let tv:mouse-default-handler track it.
- (TV:MOUSE-STANDARD-BLINKER WINDOW)
- (TV:MOUSE-DEFAULT-HANDLER WINDOW NIL))
-
- (DEFUN DEFAULT-MOUSE-MOVES-HANDLER (WINDOW X Y)
- ;; For now, in conjunction with the fact that the default
- ;; mouse-enters-window-handler makes the mouse blinker be
- ;; an ordinary arrow, just make the mouse blinker follow
- ;; the mouse.
- (TV:MOUSE-SET-BLINKER-CURSORPOS)
- (MULTIPLE-VALUE-BIND (IGNORE IGNORE SCREEN-BOX IGNORE IGNORE)
- (SCREEN-OBJ-AT-POSITION X Y WINDOW)
- (IF (GRAPHICS-SCREEN-BOX? SCREEN-BOX)
- (TELL SCREEN-BOX :HIGHLIGHT-SPRITE-UNDER-MOUSE X Y)
- (TELL *SPRITE-BLINKER* :OFF))))
-
- (DEFUN DEFAULT-MOUSE-CLICK-HANDLER (WINDOW CLICK X Y)
- ;; Get this out of the mouse process as quickly as possible.
- (TV:IO-BUFFER-CLEAR (TELL WINDOW :IO-BUFFER))
- (TELL WINDOW :FORCE-KBD-INPUT `(:MOUSE-CLICK ,WINDOW ,CLICK ,X ,Y)))
-
- (DEFUN DEFAULT-MOUSE-BUTTONS-HANDLER (WINDOW BD X Y)
- (TELL WINDOW :MOUSE-CLICK (TV:MOUSE-BUTTON-ENCODE BD) X Y))
-
- ;;; the fancy ones that might NOT work
-
- (DEFUN FANCY-MOUSE-MOVES-HANDLER (WINDOW X Y)
- ;; keep the blinker in the right place
- (TV:MOUSE-SET-BLINKER-CURSORPOS)
- ;; bind some useful values
- (MULTIPLE-VALUE-BIND (MROW MCHA-NO MSCREEN-BOX RELX RELY)
- (SCREEN-OBJ-AT-POSITION X Y WINDOW)
- (UNLESS (OR (NULL MROW)
- (AND (EQ MROW (BP-ROW *MOUSE-BP*))
- (= MCHA-NO (BP-CHA-NO *MOUSE-BP*))
- (EQ MSCREEN-BOX (BP-SCREEN-BOX *MOUSE-BP*))))
- (MOVE-BP-1 *MOUSE-BP* MROW MCHA-NO)
- (SET-BP-SCREEN-BOX *MOUSE-BP* MSCREEN-BOX)
- ;; if the mouse is in the middle of defining a region, then update the region
- (TELL-CHECK-NIL (SYMEVAL-GLOBALLY '*FOLLOWING-MOUSE-REGION*)
- :UPDATE-REDISPLAY-ALL-ROWS))
- (IF (GRAPHICS-SCREEN-BOX? MSCREEN-BOX)
- (TELL MSCREEN-BOX :HIGHLIGHT-SPRITE-UNDER-MOUSE X Y)
- (TELL *SPRITE-BLINKER* :OFF))
- (SETQ *MOUSE-BOX-X* RELX)
- (SETQ *MOUSE-BOX-Y* RELY)))
-
- ;;; these handlers get compiled in the TV package because they use LOTS of variables from
- ;;; that package.
-
- (DEFUN DONT-HIDE-THE-MOUSE-YET ()
- (OR (NOT (NULL (TELL *SPRITE-BLINKER* :SELECTED-SPRITE)))
- TV:MOUSE-RECONSIDER
- TV:MOUSE-WAKEUP))
-
- TV:
- (DEFUN BOXER:FANCY-MOUSE-ENTERS-WINDOW-HANDLER (WINDOW &AUX HAND)
- (MOUSE-STANDARD-BLINKER WINDOW)
- (MULTIPLE-VALUE-BIND (WINDOW-X-OFFSET WINDOW-Y-OFFSET)
- (SHEET-CALCULATE-OFFSETS WINDOW MOUSE-SHEET)
- (LET ((MOUSE-VISIBLE-P T))
- (LOOP FOR HIDE-MOUSE = (NOT (PROCESS-WAIT-WITH-TIMEOUT
- "Mouse Timeout" BOXER:*MOUSE-DISAPPEARING-TIMEOUT*
- #'BOXER:DONT-HIDE-THE-MOUSE-YET))
- UNTIL (OR MOUSE-RECONSIDER (NEQ WINDOW (WINDOW-OWNING-MOUSE)))
- ;; give other things a chance to break in
- DO (PROCESS-SLEEP 1.)
- WHEN (AND HIDE-MOUSE MOUSE-VISIBLE-P (NULL BOXER:*BUTTON-BEING-HELD*))
- ;; the mouse is visible but we've waited the requisite amount of time and no one
- ;; has touched the mouse so we turn the blinker off
- DO (WITHOUT-INTERRUPTS
- (SEND MOUSE-BLINKER :SET-CHARACTER #-TI #\SPACE #+TI #\@) ;should be an invisible char
- (SEND MOUSE-BLINKER :TRACK-MOUSE)
- (SETQ MOUSE-VISIBLE-P NIL))
- WHEN (AND (NULL MOUSE-VISIBLE-P) (NULL HIDE-MOUSE))
- ;; the mouse has been moved but the blinker is currently off so
- ;; we turn it back on and warp it to the current location of the cursor
- DO (WITHOUT-INTERRUPTS
- (MOUSE-STANDARD-BLINKER WINDOW)
- (MULTIPLE-VALUE-BIND (TARGET-X TARGET-Y)
- (SHEET-CALCULATE-OFFSETS BOXER:*BOXER-PANE* MOUSE-SHEET)
- (MOUSE-WARP (+ (SEND BOXER:*BOXER-PANE* :CURSOR-X) TARGET-X)
- (+ (SEND BOXER:*BOXER-PANE* :CURSOR-Y) TARGET-Y)))
- (SETQ MOUSE-VISIBLE-P T))
- WHEN (NULL HIDE-MOUSE)
- DO
- (MULTIPLE-VALUE-BIND (DX DY BD BU X Y)
- (MOUSE-INPUT NIL)
- DX DY
- (LET ((WINDOW-X (- X WINDOW-X-OFFSET))
- (WINDOW-Y (- Y WINDOW-Y-OFFSET)))
- (COND ((AND (PLUSP BD)
- BOXER:(OR *MOUSE-CLICKS-ONLY*
- (NULL *BUTTON-BEING-HELD*)))
- (SEND WINDOW :MOUSE-BUTTONS BD WINDOW-X WINDOW-Y))
- ((AND (NULL BOXER:*MOUSE-CLICKS-ONLY*)
- (BOXER:NOT-NULL BOXER:*BUTTON-BEING-HELD*)
- (PLUSP BU))
- (SEND WINDOW :MOUSE-BUTTONS BU WINDOW-X WINDOW-Y))
- (T
- (SEND WINDOW :MOUSE-MOVES WINDOW-X WINDOW-Y)
- ;(MOUSE-SET-BLINKER-CURSORPOS)
- ))
- ;; Now process button pushes if mouse is not seized
- (COND ((OR (ZEROP BD) (EQ WINDOW T) (WINDOW-OWNING-MOUSE)))
- ;; Default action for left button is to select what mouse is pointing at
- ((BIT-TEST 1 BD)
- (AND (SETQ HAND (WINDOW-UNDER-MOUSE ':MOUSE-SELECT ':ACTIVE X Y))
- ;; Next line temporarily papers over a bug with :MOUSE-SELECT
- (GET-HANDLER-FOR HAND ':SELECT)
- (MOUSE-SELECT HAND)))
- ;; Default action for middle button is to switch to the main screen
- ((BIT-TEST 2 BD)
- (IF (TYPEP MOUSE-SHEET 'SCREEN)
- (PROCESS-RUN-FUNCTION "Set mouse sheet"
- #'MOUSE-SET-SHEET DEFAULT-SCREEN)))
- ;; Default action for right button is to call the system menu
- ((BIT-TEST 4 BD)
- (MOUSE-BUTTON-ENCODE BD) ;Satisfy those who double-click out of habit
- (MOUSE-CALL-SYSTEM-MENU)))))))))
-
- #+TI(DEFVAR TV:*MOUSE-MODIFYING-KEYSTATES* '(:CONTROL :META :SUPER :HYPER))
- #+TI(EVAL-WHEN (LOAD) (SETQ TV:*MOUSE-INCREMENTING-KEYSTATES* '(:SHIFT)))
-
- TV:
- (DEFUN BOXER:FANCY-MOUSE-BUTTONS-HANDLER (WINDOW BD X Y)
- (LET ((BUTTON (1- (HAULONG BD)))) ;Pick a button that was just pushed
- (UNLESS (MINUSP BUTTON) ;Check whether a button was in fact pushed
- (LET ((MASK (LSH 1 BUTTON))
- (CH (DPB 1 %%KBD-MOUSE BUTTON))
- (TIME MOUSE-LAST-BUTTONS-TIME)
- NEW-BUTTONS NEW-TIME)
- ;; See whether we got a "double" click via the keyboard
- (DOLIST (KEY *MOUSE-INCREMENTING-KEYSTATES*)
- (WHEN (KEY-STATE KEY)
- (SETQ CH (DPB 1 %%KBD-MOUSE-N-CLICKS CH))
- (RETURN)))
- ;; Add in any control bits from the keyboard
- (DOLIST (KEY *MOUSE-MODIFYING-KEYSTATES*)
- (WHEN (KEY-STATE KEY)
- (SETQ CH (DPB 1 (SYMEVAL (CDR (ASSQ KEY '((:CONTROL . %%KBD-CONTROL)
- (:META . %%KBD-META)
- (:SUPER . %%KBD-SUPER)
- (:HYPER . %%KBD-HYPER)))))
- CH))))
- ;; De-bounce mouse and look for double clicks
- (LOOP NAMED DEBOUNCE DOING ;Do forever (until guy's finger wears out)
- ;; Ignore any clicking during the bounce delay
- (LOOP DOING (MULTIPLE-VALUE (NEW-BUTTONS NEW-TIME) (MOUSE-BUTTONS))
- UNTIL (> (TIME-DIFFERENCE NEW-TIME TIME) MOUSE-BOUNCE-TIME)
- FINALLY (SETQ TIME NEW-TIME))
- (WHEN (AND (NOT BOXER:*MOUSE-CLICKS-ONLY*) BOXER:*BUTTON-BEING-HELD*)
- ;; a held down button was raised
- (IF ( CH BOXER:*BUTTON-BEING-HELD*)
- (SETQ BOXER:*BUTTON-BEING-HELD* NIL) ;wrong button was raised
- (SEND WINDOW :MOUSE-HOLD (DPB 1 BOXER:%%KBD-MOUSE-UP-STATE CH) X Y)
- (SETQ BOXER:*BUTTON-BEING-HELD* NIL))
- (RETURN))
- (WHEN (AND BOXER:*MOUSE-CLICKS-ONLY* (NULL MOUSE-DOUBLE-CLICK-TIME))
- ;; Double-click feature disabled
- (RETURN))
- ;; Look for button to be lifted, or for double-click timeout
- (LOOP WHILE (BIT-TEST MASK NEW-BUTTONS)
- DO (MULTIPLE-VALUE (NEW-BUTTONS NEW-TIME) (MOUSE-BUTTONS))
- WHEN (AND (NOT BOXER:*MOUSE-CLICKS-ONLY*)
- (> (TIME-DIFFERENCE NEW-TIME TIME) BOXER:*MOUSE-SIGNAL-HOLD-TIME*))
- ;; Timed-out with button still down so we assume it is being HELD down
- DO (SEND WINDOW :MOUSE-HOLD CH X Y)
- (SETQ BOXER:*BUTTON-BEING-HELD* CH)
- (RETURN-FROM DEBOUNCE)
- FINALLY (SETQ TIME NEW-TIME))
- (WHEN (NULL MOUSE-DOUBLE-CLICK-TIME)
- (RETURN)) ;Double clicks disabled AND we checked for button hold
- ;; Button was lifted, do another bounce delay
- (LOOP DOING (MULTIPLE-VALUE (NEW-BUTTONS NEW-TIME) (MOUSE-BUTTONS))
- UNTIL (> (TIME-DIFFERENCE NEW-TIME TIME) MOUSE-BOUNCE-TIME)
- FINALLY (SETQ TIME NEW-TIME))
- ;; Now watch for button to be pushed again
- (LOOP UNTIL (BIT-TEST MASK NEW-BUTTONS)
- DO (MULTIPLE-VALUE (NEW-BUTTONS NEW-TIME) (MOUSE-BUTTONS))
- WHEN (> (TIME-DIFFERENCE NEW-TIME TIME) MOUSE-DOUBLE-CLICK-TIME)
- ;; Timed-out with button still up
- DO (SEND WINDOW :MOUSE-CLICK CH X Y)
- (RETURN-FROM DEBOUNCE)
- FINALLY (SETQ CH (+ CH 8) ;Count multiplicity of clicks
- TIME NEW-TIME))
- ;; Continue scanning (for triple click)
- )
- ;; Save state for next time
- (SETQ MOUSE-LAST-BUTTONS NEW-BUTTONS
- MOUSE-LAST-BUTTONS-TIME NEW-TIME)
- T))))
-
- ;;; Interface into the window system (maybe should be in BOXWIN).
- ;;; They are NOT normal window messages (like :MOUSE-CLICK) since other windows besides the
- ;;; BOXER-PANE don't handle them
-
- ;;; at some point, add another level of abstraction here like the other mouse handlers
- ;;; but it doesn't seem worth it right now
-
- (DEFMETHOD (BOXER-PANE :MOUSE-HOLD) (BUTTONS X Y)
- (TV:IO-BUFFER-CLEAR (TELL SELF :IO-BUFFER))
- (TELL SELF :FORCE-KBD-INPUT `(:MOUSE-HOLD ,SELF ,BUTTONS ,X ,Y)))
-
- ;;;; how to switch back and forth
-
- (DEFUN FANCY-MOUSE-HANDLERS ()
- (WHEN (FDEFINEDP 'FANCY-MOUSE-MOVES-HANDLER)
- (SET-MOUSE-MOVES-HANDLER 'FANCY-MOUSE-MOVES-HANDLER))
- (WHEN (FDEFINEDP 'FANCY-MOUSE-CLICK-HANDLER)
- (SET-MOUSE-CLICK-HANDLER 'FANCY-MOUSE-CLICK-HANDLER))
- (WHEN (FDEFINEDP 'FANCY-MOUSE-ENTERS-WINDOW-HANDLER)
- (SET-MOUSE-ENTERS-WINDOW-HANDLER 'FANCY-MOUSE-ENTERS-WINDOW-HANDLER))
- (WHEN (FDEFINEDP 'FANCY-MOUSE-BUTTONS-HANDLER)
- (SET-MOUSE-BUTTONS-HANDLER 'FANCY-MOUSE-BUTTONS-HANDLER))
- (SETQ *MOUSE-CLICKS-ONLY* NIL)
- T)
-
- (DEFUN RESET-MOUSE-HANDLERS ()
- (SET-MOUSE-MOVES-HANDLER 'DEFAULT-MOUSE-MOVES-HANDLER)
- (SET-MOUSE-CLICK-HANDLER 'DEFAULT-MOUSE-CLICK-HANDLER)
- (SET-MOUSE-ENTERS-WINDOW-HANDLER 'DEFAULT-MOUSE-ENTERS-WINDOW-HANDLER)
- (SET-MOUSE-BUTTONS-HANDLER 'DEFAULT-MOUSE-BUTTONS-HANDLER)
- T)
-